﻿using Application.CommonDto;
using Application.PermissionsServices.Dto;
using Entity.Permissionss;
using Entity.RolePermissionss;
using Entity.UserPermissionss;
using EntityFrameWorkCore;
using Repository.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Application.PermissionsServices
{

    public interface IPermissionsService
    {

    }

    public class PermissionsService: ApplicationServiceBase, IPermissionsService
    {
        public IRepository<Permissions, Guid, DefaultDbContext> PermissionsRep { get; set; }

        public IRepository<UserPermissions, Guid, DefaultDbContext> UserPermissionsRep { get; set; }

        public IRepository<RolePermissions, Guid, DefaultDbContext> RolePermissionsRep { get; set; }

        public async ValueTask CreatePermissions(CreatePermissionsDto dto)
            => await PermissionsRep.InsertAsync(base.MapTo<Permissions>(dto));
        

        public async ValueTask DeletePermissions(EntityDto<Guid> dto)
        {
            var delIds = new List<Guid>() { dto.Id };
            var all = await PermissionsRep.GetAllListAsync();
            foreach (var item in all.Where(x => x.ParentId == dto.Id))
            {
                delIds.Add(item.Id);
                await GetTreeId(item.Id, all, delIds);

            }

            async ValueTask GetTreeId(Guid Id ,List<Permissions> all, List<Guid> Ids)
            {
                var currs = all.Where(x => x.ParentId == Id);
                if (currs.Any())
                {
                    foreach (var curr in currs)
                    {
                        Ids.Add(curr.Id);
                        await GetTreeId(curr.Id, all, Ids);
                    }
                }
            }
            await PermissionsRep.BatchDeleteAsync(x => delIds.Contains(x.Id));
            await UserPermissionsRep.BatchDeleteAsync(x => delIds.Contains(x.PermissionsId));
            await RolePermissionsRep.BatchDeleteAsync(x => delIds.Contains(x.PermissionsId));
        }

        public async ValueTask UpdatePermissions(UpdatePermissionsDto dto)
        {

            var par = await PermissionsRep.FirstOrDefaultAsync(x => x.Id == dto.Id);
            base.Map(dto, par);
            await PermissionsRep.UpdateAsync(par);
           

        }

    

        public async ValueTask<List<TreePermissionsDto>> GetTreePermissions()
        {
           var all = await PermissionsRep.GetAllListAsync();
           var levelOnes = all.Where(x => x.ParentId is null).OrderBy( x => x.Sort);
           var outs = new List<TreePermissionsDto>();
           foreach (var level in levelOnes)
           {
                var current = new TreePermissionsDto 
                { 
                    Id = level.Id,
                    PermissionsCode = level.PermissionsCode,
                    PermissionsName = level.PermissionsName,
                    Description = level.Description,
                    Sort = level.Sort,
                    ParentId = level.ParentId,
                    Icon = level.Icon,
                    AlwaysShow = level.AlwaysShow,
                    Component = level.Component,

                };
                await GetTreeChild(current, all);
                outs.Add(current);
                       
           }
           return outs;
        }

        private async ValueTask GetTreeChild(TreePermissionsDto current, List<Permissions> all)
        {
            var currChild = all.Where(x => x.ParentId == current.Id).OrderBy(x => x.Sort);
            var childs = new List<TreePermissionsDto>();
            if (currChild.Any())
            {
                current.hasChildren = true;
                foreach (var curr in currChild)
                {
                    var child = new TreePermissionsDto 
                    { 
                        Id = curr.Id,
                        PermissionsCode = curr.PermissionsCode,
                        PermissionsName = curr.PermissionsName,
                        Description = curr.Description,
                        Sort = curr.Sort,
                        ParentId = curr.ParentId,
                        Icon = curr.Icon,
                        AlwaysShow = curr.AlwaysShow,
                        Component = curr.Component,
                    };
                    await GetTreeChild(child, all);
                    childs.Add(child);
                }
                
            }
            current.Children = childs;
        }
    }
}
